/*
 * Copyright (c) 2005-2006 FeySoft Inc. All Rights Reserved.
 */
package com.feyaSoft.home.dao.base;

import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Restrictions;

/**
 * @author fzhuang This is the base dao class for hibernate which provide the
 *         information to search list.
 */
public abstract class BaseHibernateDao {
	// private final static Logger log =
	// Logger.getLogger(BaseHibernateDao.class);

	public static final String SQL_LIKE = "like";
	public static final String SQL_IS = "is";

	/**
	 * Create general search function now...
	 * 
	 * @param querySQL
	 * @param sc
	 * @param varaibleBean
	 * @return
	 * @throws Exception
	 */
	protected BaseSearchResult commonSearch(Session session,
			Criteria basicQuery, BaseSearchCriteria sc) throws Exception {
		// get total count now
		// basicQuery.setProjection(Projections.rowCount());
		int totalCount = basicQuery.list().size();

		// get first result and max result now...
		if (sc.getFirstResult() != null && sc.getTotalResults() != null
				&& sc.getNeedCount().booleanValue()) {
			basicQuery.setFirstResult(sc.getFirstResult().intValue());
			basicQuery.setMaxResults(sc.getTotalResults().intValue());
		}

		List list = basicQuery.list();

		BaseSearchResult result = new BaseSearchResult();
		result.setResults(list);
		result.setTotalCount(new Long(totalCount));

		return result;
	}

	/**
	 * This will generate total query process, without set first result, max
	 * result...
	 * 
	 * @param session
	 * @param basicQuery
	 * @param sc
	 * @return
	 * @throws Exception
	 */
	protected BaseSearchResult totalSearch(Session session,
			Criteria basicQuery, BaseSearchCriteria sc) throws Exception {
		// get total count now
		List totalList = basicQuery.list();
		int totalCount = totalList.size();

		BaseSearchResult result = new BaseSearchResult();
		result.setResults(totalList);
		result.setTotalCount(new Long(totalCount));

		return result;
	}

	/**
	 * Create general search function for report now...
	 * 
	 * @param querySQL
	 * @param sc
	 * @param varaibleBean
	 * @return
	 * @throws Exception
	 */
	protected BaseSearchResult generalDirectSearch(Session session,
			String querySQL, VaraibleBean varaibleBean) throws Exception {
		Query query = session.createQuery(querySQL);

		setVariableInQuerySQL(query, varaibleBean);

		List list = query.list();

		BaseSearchResult result = new BaseSearchResult();
		result.setResults(list);
		result.setTotalCount(new Long(list.size()));

		return result;
	}

	/**
	 * Set variable in the SQL now...
	 * 
	 * @param query
	 * @param varaibleBean
	 * @throws Exception
	 */
	protected void setVariableInQuerySQL(Query query, VaraibleBean varaibleBean)
			throws Exception {
		try {
			List params = varaibleBean.getParamValues();
			List paramTypes = varaibleBean.getParamTypes();
			List paramNames = varaibleBean.getParamNames();

			// bind params
			if (params.size() > 0) {

				ListIterator itValues = params.listIterator();
				ListIterator itTypes = paramTypes.listIterator();
				ListIterator itNames = paramNames.listIterator();

				while (itValues.hasNext()) {
					String pType = (String) itTypes.next();
					String pName = (String) itNames.next();

					if (pType.equalsIgnoreCase("string")) {
						String pValue = (String) itValues.next();
						query.setString(pName, pValue);
					} else if (pType.equalsIgnoreCase("wildstring")) {
						String pValue = (String) itValues.next();
						query.setString(pName, "%" + pValue + "%");
					} else if (pType.equalsIgnoreCase("long")) {
						Long pValue = (Long) itValues.next();
						query.setLong(pName, pValue.longValue());
					} else if (pType.equalsIgnoreCase("int")) {
						Integer pValue = (Integer) itValues.next();
						query.setInteger(pName, pValue.intValue());
					} else if (pType.equalsIgnoreCase("list")) {
						Collection pValue = (Collection) itValues.next();
						query.setParameterList(pName, pValue);
					} else if (pType.equalsIgnoreCase("date")) {
						Date pValue = (Date) itValues.next();
						query.setDate(pName, pValue);
					}
				}
			}
		} catch (Exception e) {
			throw (new Exception("Exception during set params to query: "
					+ e.toString(), e));
		}
	}

	/**
	 * @param entities -
	 *            list of stuff with string
	 * @param property -
	 *            like | is
	 * @param alias -
	 *            pass in alias
	 * @return Disjunction
	 */
	protected Disjunction buildDisjunction(Set entities, String property,
			String alias) {
		Disjunction disjunction = Restrictions.disjunction();

		Iterator it = entities.iterator();
		while (it.hasNext()) {
			Object entity = (Object) it.next();
			if (property.equalsIgnoreCase(SQL_LIKE)) {
				entity = "%" + entity + "%";
				disjunction.add(Restrictions.like(alias, entity).ignoreCase());
			} else {
				disjunction.add(Restrictions.eq(alias, entity));
			}
		}

		return disjunction;
	}

	/**
	 * @param entities -
	 *            list of stuff with string
	 * @param property -
	 *            like | is
	 * @param alias -
	 *            pass in alias - a list of string
	 * @return Disjunction
	 */
	protected Disjunction buildDisjunction(Set entities, String property,
			String[] alias) {
		Disjunction disjunction = Restrictions.disjunction();

		Iterator it = entities.iterator();
		while (it.hasNext()) {
			Object entity = (Object) it.next();
			if (property.equalsIgnoreCase(SQL_LIKE)) {
				entity = "%" + entity + "%";
				for (int i = 0; i < alias.length; i++) {
					disjunction.add(Restrictions.like(alias[i], entity)
							.ignoreCase());
				}
			} else {
				for (int i = 0; i < alias.length; i++) {
					disjunction.add(Restrictions.eq(alias[i], entity));
				}
			}
		}

		return disjunction;
	}

}
